#include "Timer.h"
#include "DateTime.h"
#include "Tracer.h"
#include <signal.h>

namespace libemb{
Timer::Timer(TimerListener* listener,int timerID)
{
}

Timer::~Timer()
{

}

bool Timer::start(int msTimeout, bool repeat)
{
	if (msTimeout<=0 || m_timerID<0)
	{
		TRACE_ERR_CLASS("Param Error,timerID:%d, timeout:%d\n",m_timerID,msTimeout);
		return false;
	}
	m_msTimeout = msTimeout;
	if (repeat)
	{
		m_msInterval = m_msTimeout;
	}
	else
	{
		m_msInterval = 0;
	}
	m_startFlag = true;
	return true;
}
void Timer::stop()
{
	m_startFlag = false;
}

void Timer::reduce(int ms)
{
	if (!m_startFlag)
	{
		return;
	}
	m_msTimeout -= ms;
	if (m_msTimeout<=0)
	{
		if(m_msInterval==0)
		{
			m_startFlag = false;
		}
		else
		{
			m_msTimeout = m_msInterval;
		}
		
		if (m_listener!=NULL)
		{
			m_listener->onTimer(m_timerID);
		}
	}
}

bool TimerManager::initWithTick(int msTickInterval)
{
	if (msTickInterval<=0)
	{
		TRACE_ERR_CLASS("Param Error, tick interval:%d\n",msTickInterval);
		return false;
	}
	#if 0	/* sigaction目前有问题,暂不清楚什么原因. */
	/* 安装信号处理函数 */
	struct sigaction act;
	memset(&act,0,sizeof(act));
	act.sa_handler = onSignal;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);
	if(sigaction(SIGUSR1,&act,NULL)<0)
	{
		TRACE_ERR_CLASS("sigaction error:%s\n",ERRSTR);
		return false;
	}
	#else
	signal(SIGUSR1,onSignal);/* 有些系统signal安装好处理函数后只生效一次,但目前测试并不是这样的 */
	#endif	

	/* 创建基准定时器(用信号实现,但信号会影响很多系统调用,导致提前退出,比如select,sleep等) */
	struct sigevent evt;
	memset(&evt,0,sizeof(evt));
	evt.sigev_notify = SIGEV_SIGNAL;
	evt.sigev_signo  = SIGUSR1;
	evt.sigev_value.sival_ptr = &m_baseTimer;
	if(timer_create(CLOCK_MONOTONIC,&evt,&m_baseTimer)<0)
	{
		TRACE_ERR_CLASS("timer create error:%s\n",ERRSTR);
		return false;
	}

	/* 启动基准定时器 */
	struct itimerspec ts;
	ts.it_interval.tv_sec =msTickInterval/1000;
	ts.it_interval.tv_nsec=(msTickInterval%1000)*1000000;
	ts.it_value.tv_sec = ts.it_interval.tv_sec;
	ts.it_value.tv_nsec = ts.it_interval.tv_nsec;
	if (timer_settime(m_baseTimer,0,&ts,0)<0)
	{
		TRACE_ERR_CLASS("timer settime error:%s\n",ERRSTR);
		return false;
	}
	m_msTickInterval = msTickInterval;
	return true;
}


/**
 *  \brief  注册定时器
 *  \param  timer 定时器
 *  \return 成功返回true,失败返回false
 *  \note   none
 */
bool TimerManager::registerTimer(std::shared_ptr<Timer> timer)
{
	AutoLock lock(m_tmrlstMutex);
	for(auto tmr : m_timerList)
	{
		if (tmr==timer)
		{
			return false;
		}
	}
	timer->m_startFlag=false;
	m_timerList.push_back(timer);
	return true;
}

/**
 *  \brief  注销定时器
 *  \param  timer 定时器
 *  \return 成功返回true,失败返回false
 *  \note   none
 */
bool TimerManager::unregisterTimer(std::shared_ptr<Timer> timer)
{
	AutoLock lock(m_tmrlstMutex);
	for(auto iter=m_timerList.begin();iter!=m_timerList.end();iter++)
	{
		if(*iter == timer)
		{
			m_timerList.erase(iter);
			return true;
		}
	}
	return false;
}

void TimerManager::onTick()
{
	AutoLock lock(m_tmrlstMutex);
	for(auto tmr : m_timerList)
	{
		tmr->reduce(m_msTickInterval);
	}
}

void TimerManager::onSignal(int signo)
{
	if (signo==SIGUSR1)
	{
		//TRACE_REL("handle SIGUSR1.\n");
		TimerManager::getInstance().onTick();
	}
}

/**
 *  \brief  RTimer构造函数
 *  \param  thread 定时器所依附的线程
 *  \param  listener 定时器监听者
 *  \param  id 定时器ID
 */
RTimer::RTimer(const Thread& thread,const TimerListener& listener,int id):
m_timerID(id)
{
	m_listener = const_cast<TimerListener*>(&listener);
	m_thread = const_cast<Thread*>(&thread);
	m_thread->start(*this);
}

RTimer::~RTimer()
{
	stop();
	if (m_thread->isRunning() && !m_thread->stop(300))
	{
		m_thread->forceQuit();
	}
}

/**
 *  \brief  启用定时器
 *  \param  usTimeout 定时时间
 *  \param  repeat 是否重复(周期定时)
 *  \return 成功返回true,失败返回false
 *  \note   因此定时时间的最小值依赖于系统实时性,定时时间越小,精度越差,定时器线程负荷也越重.
 */
bool RTimer::start(int usTimeout,bool repeat)
{
    if (usTimeout<=0 || m_timerID<0 || m_listener==NULL)
	{
		TRACE_ERR_CLASS("Param Error, id:%d, timeout:%d, listener:0x%x\n",m_timerID,usTimeout,m_listener);
		return false;
	}
    m_usTimeout = usTimeout;
	if (repeat)
	{
		m_usInterval = m_usTimeout;
	}
	else
	{
		m_usInterval = 0;
	}
	m_startFlag = true;
    return true;
}

/**
 *  \brief  停止定时器
 *  \param  none
 *  \return none
 *  \note   none
 */
void RTimer::stop()
{
    m_startFlag = false;        
}

void RTimer::run()
{
	bool firstTime=true;
	Time lastTime,currTime;
	int timeDiff;
    while (isRunning()) 
    {
        if (m_startFlag)
        {
        	if (firstTime)
        	{
				lastTime = Time::currentTimeMonotonic();
				firstTime = false;
			}
			else
			{
				currTime = Time::currentTimeMonotonic();
				Time timeDiff = currTime-lastTime;
				int usOver = (int)(timeDiff.toMicroSeconds()) - m_usInterval;
				if(usOver>=0)/* 到了定时时间 */
				{
					//TRACE_DBG("RTimer usOver=%d\n",usOver);
					if (usOver>m_usInterval)
					{
						TRACE_WARN("RTimer over run interval: %d > %d\n",usOver,m_usInterval);
						lastTime = currTime;/* 已经超过一个周期了,重新计算差值 */
					}
					else
					{
						Time overTime(0,usOver);
						lastTime = currTime-overTime;/* 减去超过的时间 */
					}
					
					if (m_listener!=NULL)
	                {
	                	m_listener->onTimer(m_timerID);
	            	}
				}
			}
			/* 每100us读一次时间 */
            Thread::usleep(100);
        }
        else
        {
        	firstTime = true;
			Thread::usleep(100);
			continue;
        }
    }
}
}
